﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BooruViewer.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace BooruViewer.Models
{
    public partial class E621
    {
        [JsonProperty("id")]
        public long Id { get; set; }

        [JsonProperty("tags")]
        public string Tags { get; set; }

        [JsonProperty("locked_tags")]
        public object LockedTags { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }

        [JsonProperty("created_at")]
        public CreatedAt CreatedAt { get; set; }

        [JsonProperty("creator_id")]
        public long? CreatorId { get; set; }

        [JsonProperty("author")]
        public string Author { get; set; }

        [JsonProperty("change")]
        public long Change { get; set; }

        [JsonProperty("source")]
        public Uri Source { get; set; }

        [JsonProperty("score")]
        public long Score { get; set; }

        [JsonProperty("fav_count")]
        public long FavCount { get; set; }

        [JsonProperty("md5")]
        public string Md5 { get; set; }

        [JsonProperty("file_size")]
        public long FileSize { get; set; }

        [JsonProperty("file_url")]
        public Uri FileUrl { get; set; }

        [JsonProperty("file_ext")]
        public string FileExt { get; set; }

        [JsonProperty("preview_url")]
        public Uri PreviewUrl { get; set; }

        [JsonProperty("preview_width")]
        public long PreviewWidth { get; set; }

        [JsonProperty("preview_height")]
        public long PreviewHeight { get; set; }

        [JsonProperty("sample_url")]
        public Uri SampleUrl { get; set; }

        [JsonProperty("sample_width")]
        public long SampleWidth { get; set; }

        [JsonProperty("sample_height")]
        public long SampleHeight { get; set; }

        [JsonProperty("rating")]
        public string Rating { get; set; }

        [JsonProperty("status")]
        public string Status { get; set; }

        [JsonProperty("width")]
        public long Width { get; set; }

        [JsonProperty("height")]
        public long Height { get; set; }

        [JsonProperty("has_comments")]
        public bool HasComments { get; set; }

        [JsonProperty("has_notes")]
        public bool HasNotes { get; set; }

        [JsonProperty("has_children")]
        public bool HasChildren { get; set; }

        [JsonProperty("children")]
        public string Children { get; set; }

        [JsonProperty("parent_id")]
        public long? ParentId { get; set; }

        [JsonProperty("artist")]
        public string[] Artist { get; set; }

        [JsonProperty("sources")]
        public Uri[] Sources { get; set; }
    }

    public partial class CreatedAt
    {
        [JsonProperty("json_class")]
        public string JsonClass { get; set; }

        [JsonProperty("s")]
        public long S { get; set; }

        [JsonProperty("n")]
        public long N { get; set; }
    }

    public partial class E621
    {
        public static E621[] FromJson(string json) => JsonConvert.DeserializeObject<E621[]>(json, E621Converter.Settings);
    }

    internal static class E621Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters = {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
    

    public static class E621Helpers
    {
        /// <summary>
        /// Coverts the Danbooru array object to a list of BImage objects
        /// </summary>
        /// <param name="e621"></param>
        /// <returns></returns>
        public static List<BImage> E621ToImages(this E621[] e621)
        {
            List<BImage> imgs = new List<BImage>();

            int i = 1;
            foreach (var d in e621)
            {
                var tags = d.Tags.Split(' ');

                imgs.Add(new BImage(
                    d.Id.ToString(),
                    d.PreviewUrl.ToString(),
                    d.FileUrl.ToString(),
                    d.Artist,
                    tags,
                    d.FileExt,
                    d.Score
                ));
                i++;
            }

            return imgs;
        }

        /// <summary>
        /// Gets a Query object and parses it into a Danbooru-specific query string
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        public static string BuildE621(this Query q, string url = "http://e621.net")
        {
            // Base endpoint
            string query = url+"/post/index.json?tags=";

            // Tags
            query += q.Tags
                    .TrimEnd(' ')
                    .Replace(" ", "%20");

            // Rating
            string rating = "";

            if (q.Ratings.Contains(Rating.Safe))
                rating += "rating:s ";
            if (q.Ratings.Contains(Rating.Questionable))
                rating += "rating:q ";
            if (q.Ratings.Contains(Rating.Explicit))
                rating += "rating:e ";
            rating = rating.TrimEnd(' ').Replace(" ", "%20~");

            if (rating != "")
                rating = "%20" + rating;

            query += rating;

            //Prepare score query
            string score = "";

            if (q.MinScore != null && q.MaxScore != null)
            {
                score += q.MinScore;
                score += "..";
                score += q.MaxScore;
            }
            else
            {
                if (q.MinScore!= null)
                    score += q.MinScore;
                if (q.MaxScore != null)
                    score += q.MaxScore;
            }

            if (score != "")
                score = "%20score:" + score;

            query += score;

            // Add page number
            query += "&page=" + q.Page;
            
            // Add limit
            query += "&limit=30";

            return query;

        }
    }
}
